package com.boot.utils;

import cn.hutool.json.JSONUtil;
import com.boot.entity.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.search.SearchHit;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * DESC: Elasticsearch工具类
 *
 * @author WangJie
 * @date Created in 2025-04-20 9:58
 */
@Slf4j
public class ElasticSearchUtils {

    /**
     * 创建Elasticsearch索引
     */
    public void createIndex(String indexName, RestHighLevelClient restHighLevelClient) throws IOException {
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 删除Elasticsearch索引
     */
    public void deleteIndex(String indexName, RestHighLevelClient restHighLevelClient) throws IOException {
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
        AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().  delete(deleteIndexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 检查Elasticsearch索引是否存在
     */
    public static boolean checkIndexExists(String indexName, RestHighLevelClient restHighLevelClient) throws IOException {
        return restHighLevelClient.indices().exists(new GetIndexRequest(indexName), RequestOptions.DEFAULT);
    }

    /**
     * 插入数据到Elasticsearch索引
     */
    public static<T> void insertData(String indexName, String documentId, Object document, RestHighLevelClient restHighLevelClient) throws IOException {
        // 创建IndexRequest
        IndexRequest indexRequest = new IndexRequest(indexName).id(documentId).source(JSONUtil.toJsonStr(document), XContentType.JSON);
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        log.info("index response:{}", JSONUtil.toJsonStr(indexResponse));
    }

    /**
     * 更新Elasticsearch索引数据
     */
    public static <T> void updateData(String indexName, String documentId, Object document, RestHighLevelClient restHighLevelClient) throws IOException {
        // 创建UpdateRequest
        UpdateRequest updateRequest = new UpdateRequest(indexName, documentId).doc(JSONUtil.toJsonStr(document), XContentType.JSON);
        UpdateResponse updateResponse = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        log.info("update response:{}", JSONUtil.toJsonStr(updateResponse));
    }

    /**
     * 更新或插入Elasticsearch索引数据
     */
    public static <T> void insertOrUpdateData(String indexName, String documentId, Object document, RestHighLevelClient restHighLevelClient) throws IOException {
        // 创建IndexRequest
        IndexRequest indexRequest = new IndexRequest(indexName).id(documentId).source(JSONUtil.toJsonStr(document), XContentType.JSON);
        IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
        log.info("index response:{}", JSONUtil.toJsonStr(indexResponse));
    }

    /**
     * 删除Elasticsearch索引数据
     */
    public static void deleteData(String indexName, String documentId, RestHighLevelClient restHighLevelClient) throws IOException {
        // 创建DeleteRequest
        DeleteResponse deleteResponse = restHighLevelClient.delete(new DeleteRequest(indexName, documentId), RequestOptions.DEFAULT);
        log.info("delete response:{}", JSONUtil.toJsonStr(deleteResponse));
    }

    /**
     * 查询Elasticsearch索引数据
     */
    public static <T> List<T> searchData(SearchRequest searchRequest, Class<T> clazz, RestHighLevelClient restHighLevelClient) throws IOException {
        log.info("search request:{}", JSONUtil.toJsonStr(searchRequest));
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        log.info("search response:{}", JSONUtil.toJsonStr(searchResponse));
        // 解析查询结果
        List<T> list = new ArrayList<>();
        for (SearchHit searchHit : searchResponse.getHits().getHits()) {
            list.add(JSONUtil.toBean(searchHit.getSourceAsString(), clazz));
        }
        return list;
    }

    /**
     * 分页查询Elasticsearch索引数据
     */
    public static <T> PageInfo<T> searchDataByPage(SearchRequest searchRequest, Class<T> clazz, RestHighLevelClient restHighLevelClient) throws IOException {
        log.info("search request:{}", JSONUtil.toJsonStr(searchRequest));
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        log.info("search response:{}", JSONUtil.toJsonStr(searchResponse));
        // 解析查询结果
        List<T> list = new ArrayList<>();
        for (SearchHit searchHit : searchResponse.getHits().getHits()) {
            list.add(JSONUtil.toBean(searchHit.getSourceAsString(), clazz));
        }
        PageInfo<T> pageInfo = new PageInfo<>();
        pageInfo.setTotal(searchResponse.getHits().getTotalHits().value);
        pageInfo.setList(list);
        return pageInfo;
    }

    /**
     * 批量插入数据到Elasticsearch索引
     */
    public static <T> void bulkInsertData(String indexName, List<T> documentList, RestHighLevelClient restHighLevelClient) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        for (T document : documentList) {
            // todo: 根据实际情况设置文档id
            IndexRequest indexRequest = new IndexRequest(indexName).source(JSONUtil.toJsonStr(document), XContentType.JSON);
            bulkRequest.add(indexRequest);
        }
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    }

}
